package cn.ilikes.tools.nosql.jpa.clients.indexs.index.lucenes.asytools;

import java.io.IOException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.clients.indexs.ClientIndexingRunTimeException;
import cn.ilikes.tools.nosql.jpa.clients.indexs.index.ABIndexSource;
import cn.ilikes.tools.nosql.jpa.clients.indexs.index.ABLuceneIndexSource;

public class AsySingLuceneService implements IAsyLuceneService {

	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private int i=0;

	private ReadLock readlock = lock.readLock();

	private WriteLock writeLock = lock.writeLock();
	
	private boolean  wirte=false;

	private static IAsyLuceneService syLuceneService;

	private ABLuceneIndexSource indexSource;

	private Analyzer analyzer;

	private Logger logger = Loggerfactory.instance(AsySingLuceneService.class);

	private boolean init = false;

	private IndexWriter nowIndexWriter;

	private IndexSearcher indexSearcher;

	private IndexReader indexReader;

	private AsySingLuceneService(ABIndexSource indexSource, Analyzer analyzer) {
		this.analyzer = analyzer;
		this.indexSource = (ABLuceneIndexSource) indexSource;
		init();

	}

	private static synchronized void create(ABIndexSource indexSource, Analyzer analyzer) {
		syLuceneService = new AsySingLuceneService(indexSource, analyzer);

	}

	public static IAsyLuceneService instance(ABIndexSource indexSource, Analyzer analyzer) {
		if (syLuceneService == null) {
			create(indexSource, analyzer);
		}
		Loggerfactory.print("this  AsySingLuceneService  is :   " + syLuceneService.toString());
		return syLuceneService;
	}

	@Override
	public void close() {
		if (nowIndexWriter != null)
			try {
				nowIndexWriter.close();
			} catch (IOException e) {

				e.printStackTrace();
			}
		if (this.indexReader != null)
			try {
				indexReader.close();
			} catch (IOException e) {

				e.printStackTrace();
			}
	}

	@Override
	public IndexWriter createIndexWriter() {
		if (nowIndexWriter == null) {
			synchronized (logger) {
				try {
					RAMDirectory nowDirectory = new RAMDirectory();
					IndexWriter indexWriter = new IndexWriter(nowDirectory, new IndexWriterConfig(Version.LUCENE_41, analyzer));
					this.nowIndexWriter = indexWriter;
					wirte=false;
					i=0;
				} catch (IOException e) {
					Loggerfactory.error(logger, e.getMessage(), e);
					throw new ClientIndexingRunTimeException(e);
				}
			}
		}
		return nowIndexWriter;

		//		try {
		//			if (nowIndexWriter == null) {
		//				IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_41, this.analyzer);
		//				ABLuceneIndexSource luceneIndexSource = indexSource;
		//				Directory directory_ = luceneIndexSource.createDirectory();
		//				IndexWriter hdfsIndexWriter = new IndexWriter(directory_, indexWriterConfig);
		//				this.nowIndexWriter = hdfsIndexWriter;
		//			}
		//			return nowIndexWriter;
		//		} catch (IOException e) {
		//			Loggerfactory.error(logger, e.getMessage(), e);
		//			throw new ClientIndexingRunTimeException(e);
		//		}

	}

	public IndexSearcher createIndexSearcher() {
		if (indexSearcher == null) {
			synchronized (logger) {
				try {
					IndexReader reader = createIndexReader();
					if (Loggerfactory.isdebug(logger))
						Loggerfactory.info(logger, "create     index searcher " + reader);
					if (reader == null)
						return null;
					IndexSearcher searcher = new IndexSearcher(reader);
					this.indexSearcher = searcher;
				} catch (Exception e) {
					Loggerfactory.error(logger, e.getMessage(), e);
				}
			}
		}
		return indexSearcher;
	}

	public IndexReader createIndexReader() {

		if (indexReader == null) {
			synchronized (logger) {
				try {
					ABLuceneIndexSource luceneIndexSource = indexSource;
					if (Loggerfactory.isdebug(logger))
						Loggerfactory.info(logger, "create  " + luceneIndexSource.getIndexConfigs().getName() + "  index reader  " + this.indexReader);
					Directory directory = luceneIndexSource.createDirectory();
					//					IndexWriter indexWriter = createIndexWriter();
					//					IndexReader reader = DirectoryReader.open(indexWriter, true);
					IndexReader reader = DirectoryReader.open(directory);
					this.indexReader = reader;
					System.out.println("=========  createIndexReader =========   " + this.indexReader);
				} catch (Exception e) {
					Loggerfactory.error(logger, e.getMessage());
				}
			}
		}
		return indexReader;
	}

	@Override
	public void init() {
		if (init)
			return;
		init = true;
		createIndexWriter();
		createIndexReader();

	}

	@Override
	public void wirte(Document doc) {

		try {
			readlock.lock();
			wirte=true;
			i++;
			IndexWriter indexWriter = createIndexWriter();
			indexWriter.addDocument(doc);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			readlock.unlock();
		}

	}

	@Override
	public void merg() {
		if(!wirte)return;
		Directory nowDirectory=null;
		try {
			writeLock.lock();
			this.nowIndexWriter.close();
			nowDirectory=this.nowIndexWriter.getDirectory();
			System.out.println("================ merg  i  "+i);
			this.nowIndexWriter=null;
			this.nowIndexWriter = createIndexWriter();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			writeLock.unlock();
		}
		if(nowDirectory!=null)
		{
			IndexWriter hdfsIndexWriter=null;
			try {
			IndexWriterConfig  indexWriterConfig=new IndexWriterConfig(Version.LUCENE_41, this.analyzer);
			ABLuceneIndexSource luceneIndexSource = this.indexSource;
			Directory directory_ = luceneIndexSource.createDirectory();
			hdfsIndexWriter = new IndexWriter(directory_, indexWriterConfig);
			hdfsIndexWriter.addIndexes(nowDirectory);
			hdfsIndexWriter.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if(hdfsIndexWriter!=null)
					try {
						hdfsIndexWriter.close();
					} catch (IOException e) {
						
						e.printStackTrace();
					}
			}
		}
		

	}

}
